package service

import (
	"database/sql"
	"encoding/json"
	"errors"
	"fmt"
	"goframe-zc/dto"
	"goframe-zc/utility"
	"strconv"
	"strings"

	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gtime"
)

// Lhbd 单例模式（全局唯一实例）
var Lhbd = lhbdService{}

type lhbdService struct{}

const (
	registerURL     = "https://www.chuhanzhilian.com:8081/userInfo/addUser"
	token           = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjdXJyZW50VGltZU1pbGxpcyI6MTc2Mzk0OTgyOTQ3NywidXNlcklkIjoiNSJ9.iVRW5Mw84zH8OFaoqoizIUKqdhxWsqCYF5uVjpZUJgo"
	minPoints       = 300
	defaultReferrer = "15138382999"
	createTime      = "2025-11-30 00:00:00"
)

func (s *lhbdService) LhbdToZlyc(ctx g.Ctx) (interface{}, error) {
	// 1. 查询待处理的迁移用户
	migrateUsers, err := s.getPendingMigrateUsers()
	if err != nil {
		return "智链影创-平移-错误", err
	}

	if len(migrateUsers) == 0 {
		return "智链影创-平移表-没有需要处理的数据", nil
	}

	result := s.processMigrationBatch(ctx, migrateUsers)
	return result.ToMap(), nil
}

// getPendingMigrateUsers 获取待处理的迁移用户
func (s *lhbdService) getPendingMigrateUsers() ([]*dto.ZlycMigrateUsers, error) {
	var users []*dto.ZlycMigrateUsers
	err := g.DB("mysql_zlyc").Model("zlyc_migrate_users_lhbd").
		Where("status", 0).
		Scan(&users)
	return users, err
}

// processMigrationBatch 批量处理用户迁移
func (s *lhbdService) processMigrationBatch(ctx g.Ctx, migrateUsers []*dto.ZlycMigrateUsers) *migrationResult {
	var (
		resMsg   strings.Builder
		phoneArr []string
	)

	for _, user := range migrateUsers {
		phoneArr = append(phoneArr, user.ZlycPhone)

		processErr := s.processSingleUserMigration(ctx, user, &resMsg)
		if processErr != nil {
			s.updateUserStatus(int(user.Id), -1, &resMsg)
			continue
		}
	}

	return &migrationResult{
		Message:  resMsg.String(),
		PhoneArr: phoneArr,
	}
}

// processSingleUserMigration 处理单个用户迁移
func (s *lhbdService) processSingleUserMigration(ctx g.Ctx, migrateUser *dto.ZlycMigrateUsers, resMsg *strings.Builder) error {
	// 验证前置条件
	if err := s.validatePreconditions(migrateUser); err != nil {
		resMsg.WriteString(err.Error() + ",")
		return err
	}

	lhbdUser, err2 := s.findLhbdUser(migrateUser.Phone)
	if err2 != nil || lhbdUser == nil {
		resMsg.WriteString("莲花宝典-用户表-未找到该号码用户,")
		return fmt.Errorf("莲花宝典-用户表-未找到该号码用户")
	}

	points := s.calculateValidPoints(migrateUser)
	// 创建或更新智链影创账户
	zlycUser, err := s.createOrUpdateZlycAccount(ctx, migrateUser, points, resMsg)
	if err != nil {
		return err
	}
	// 转移订单数据和积分
	if err := s.transferOrderData(lhbdUser, zlycUser, points, resMsg); err != nil {
		return err
	}

	// 清理原始用户数据
	if err := s.deleteLhbdUser(int(migrateUser.Id)); err != nil {
		return err
	}

	return s.markUserAsProcessed(int(migrateUser.Id), resMsg)
}

// validatePreconditions 验证迁移前提条件
func (s *lhbdService) validatePreconditions(user *dto.ZlycMigrateUsers) error {
	switch {
	case user.PaperPointSum > user.TablePointSum:
		return fmt.Errorf("纸质积分大于数据表积分不平移")
	case s.calculateValidPoints(user) < minPoints:
		return fmt.Errorf("积分小于%d的不平移", minPoints)
	default:
		return nil
	}
}

// findLhbdUser 查找莲花宝典用户
func (s *lhbdService) findLhbdUser(phone string) (*dto.ZlycUserInfo, error) {
	var user dto.ZlycUserInfo
	err := g.DB("mysql_lhbd").Model("user_info").
		Where("username", phone).
		Scan(&user)

	if err != nil {
		return nil, err
	}

	return &user, nil
}

// calculateValidPoints 计算有效积分
func (s *lhbdService) calculateValidPoints(user *dto.ZlycMigrateUsers) float64 {
	if user.TablePointSum < user.PaperPointSum {
		return user.TablePointSum
	}
	return user.PaperPointSum
}

// createOrUpdateZlycAccount 创建或更新智链影创账户
func (s *lhbdService) createOrUpdateZlycAccount(
	ctx g.Ctx,
	migrateUser *dto.ZlycMigrateUsers,
	points float64, resMsg *strings.Builder,
) (*dto.ZlycUserInfo, error) {
	resMsg.WriteString(migrateUser.ZlycPhone)
	existingUser, err := s.checkExistingZlycUser(migrateUser.ZlycPhone)
	if err != nil {
		return nil, err
	}

	if existingUser != nil {
		// 更新现有用户积分
		existingUser.GreenPointsAmount += points
		resMsg.WriteString("账号已注册,用户id:" + strconv.Itoa(existingUser.Id) + ",")
		resMsg.WriteString("修改积分:" + strconv.FormatFloat(points, 'f', 2, 64) + ",")
		return existingUser, s.saveZlycUser(existingUser)
	} else {
		// 创建新用户
		newUser, err := s.registerNewZlycUser(ctx, migrateUser, points)
		if err != nil {
			return nil, err
		}
		// 修改新用户积分
		newUser.GreenPointsAmount = points
		err = s.saveZlycUser(newUser)
		if err != nil {
			return nil, err
		}
		resMsg.WriteString("注册成功,用户id:" + strconv.Itoa(newUser.Id) + ",")
		resMsg.WriteString("修改积分:" + strconv.FormatFloat(points, 'f', 2, 64) + ",")
		return newUser, nil
	}
}

// checkExistingZlycUser 检查智链影创用户是否存在
func (s *lhbdService) checkExistingZlycUser(phone string) (*dto.ZlycUserInfo, error) {
	var user dto.ZlycUserInfo
	err := g.DB("mysql_zlyc").Model("user_info").
		Where("username", phone).
		Scan(&user)

	if err != nil && !errors.Is(err, sql.ErrNoRows) {
		return nil, err
	}

	if errors.Is(err, sql.ErrNoRows) {
		return nil, nil
	}

	return &user, nil
}

// registerNewZlycUser 注册新的智链影创用户
func (s *lhbdService) registerNewZlycUser(
	ctx g.Ctx,
	migrateUser *dto.ZlycMigrateUsers,
	points float64,
) (*dto.ZlycUserInfo, error) {
	var user *dto.ZlycUserInfo
	referrer := s.determineReferrer(migrateUser.Referrer)

	sharedCode, err := s.generateShareCode(referrer)
	if err != nil {
		return nil, err
	}

	// 调用外部API注册
	if err := s.callRegisterAPI(ctx, migrateUser.ZlycPhone, sharedCode); err != nil {
		return nil, err
	}

	// 本地数据库创建用户
	//user := &dto.ZlycUserInfo{
	//	Username:          migrateUser.ZlycPhone,
	//	Phone:             migrateUser.ZlycPhone,
	//	GreenPointsAmount: points,
	//	Shared:            1608,
	//}

	err = g.DB("mysql_zlyc").Model("user_info").Where("username", migrateUser.ZlycPhone).Scan(&user)
	if err != nil {
		return nil, fmt.Errorf("err16: %v", err)
	}
	g.Log().Debugf(ctx, "新用户注册成功 ID: %d", user.Id)
	return user, nil
}

// determineReferrer 确定推荐人
func (s *lhbdService) determineReferrer(customReferrer string) string {
	if customReferrer != "" {
		return customReferrer
	}
	return defaultReferrer
}

// generateShareCode 生成分享码
func (s *lhbdService) generateShareCode(referrer string) (string, error) {
	var referrerUser dto.ZlycUserInfo
	err := g.DB("mysql_zlyc").Model("user_info").
		Where("username", referrer).
		Scan(&referrerUser)

	if err != nil {
		return "", fmt.Errorf("推荐人查询失败: %v", err)
	}

	return fmt.Sprintf("ZLYC%d", referrerUser.Id), nil
}

// callRegisterAPI 调用注册API
func (s *lhbdService) callRegisterAPI(ctx g.Ctx, phone, shareCode string) error {
	param := map[string]string{
		"username":   phone,
		"sharedCode": shareCode,
	}

	jsonData, err := json.Marshal(param)
	if err != nil {
		return fmt.Errorf("参数序列化失败: %v", err)
	}

	data, err := utility.PostThirdPartyData(ctx, registerURL, string(jsonData), token)
	if err != nil {
		return fmt.Errorf("API调用失败: %v", err)
	}

	if data.Code != 200 {
		return fmt.Errorf("API响应异常: code=%d", data.Code)
	}

	return nil
}

// saveZlycUser 保存智链影创用户信息
func (s *lhbdService) saveZlycUser(user *dto.ZlycUserInfo) error {
	_, err := g.DB("mysql_zlyc").Model("user_info").
		Where("username", user.Username).
		Data(user).Update()
	return err
}

// transferOrderData 转移订单数据
func (s *lhbdService) transferOrderData(
	lhbdUser, zlycUser *dto.ZlycUserInfo,
	points float64, resMsg *strings.Builder,
) error {
	orders, totalAmount, err := s.getLhbdOrders(lhbdUser.Id)
	if err != nil {
		return err
	}

	if orders == nil {
		return fmt.Errorf("莲花宝典-订单表-数据为空")
	}

	// 插入新订单记录
	orders[0].UserId = zlycUser.Id
	orderID, err := s.insertZlycOrder(orders[0], totalAmount)
	if err != nil {
		return err
	}
	resMsg.WriteString("订单id:" + strconv.FormatInt(orderID, 10) + ",")
	resMsg.WriteString("订单金额:" + strconv.FormatFloat(totalAmount, 'f', 2, 64) + ",")
	// 创建积分关联记录
	if err := s.createGreenPointsRecord(zlycUser.Id, int(orderID), points); err != nil {
		return err
	}

	return nil
}

// getLhbdOrders 获取莲花宝典订单
func (s *lhbdService) getLhbdOrders(userID int) ([]*dto.OrderInfo, float64, error) {
	var orders []*dto.OrderInfo

	err := g.DB("mysql_lhbd").Model("order_info").
		Where("user_id", userID).
		Where("order_type", 1).
		WhereIn("status", []int{2, 3, 4}).
		Scan(&orders)
	if err != nil {
		return nil, 0, err
	}

	totalAmount, err := g.DB("mysql_lhbd").Model("order_info oi").
		LeftJoin("user_order_green_integral ogi", "ogi.order_id = oi.id").
		Where("oi.user_id", userID).
		Where("oi.order_type", 1).
		Where("ogi.residue_green_integral > ?", 0).
		WhereIn("oi.status", []int{2, 3, 4}).
		Sum("price")
	if err != nil {
		return nil, 0, err
	}

	return orders, totalAmount, nil
}

// insertZlycOrder 插入智链影创订单
func (s *lhbdService) insertZlycOrder(sourceOrder *dto.OrderInfo, amount float64) (int64, error) {
	sourceOrder.Price = amount
	sourceOrder.Status = 5
	sourceOrder.Id = 0
	id, err := g.DB("mysql_zlyc").Model("order_info").
		Data(sourceOrder).InsertAndGetId()
	if err != nil {
		return 0, fmt.Errorf("订单插入失败: %v", err)
	}

	return id, nil
}

// createGreenPointsRecord 创建绿积分记录
func (s *lhbdService) createGreenPointsRecord(userID, orderID int, points float64) error {
	record := &dto.UserOrderGreenIntegral{
		UserId:               userID,
		OrderId:              orderID,
		ResidueGreenIntegral: points,
		CreateTime:           gtime.NewFromStr(createTime),
		UpdateTime:           gtime.NewFromStr(createTime),
	}

	_, err := g.DB("mysql_zlyc").Model("user_order_green_integral").
		Data(record).InsertAndGetId()
	return err
}

// deleteLhbdUser 删除莲花宝典用户
func (s *lhbdService) deleteLhbdUser(userID int) error {
	_, err := g.DB("mysql_lhbd").Model("user_info").
		Where("id", userID).Delete()
	// 模拟假删除
	//_, err := g.DB("mysql_lhbd").Model("user_info").
	//	Where("id", userID).One()
	return err
}

// markUserAsProcessed 标记用户为已处理
func (s *lhbdService) markUserAsProcessed(userID int, resMsg *strings.Builder) error {
	//updateData := &dto.ZlycMigrateUsers{
	//	Id:     uint64(userID),
	//	Status: 1,
	//	Res:    fmt.Sprintf("处理成功-%s", processMsg),
	//}
	updateData := g.Map{
		"status": 1,
		"res":    fmt.Sprintf("处理成功-%s", resMsg),
	}
	_, err := g.DB("mysql_zlyc").Model("zlyc_migrate_users_lhbd").
		Where("id", userID).
		Data(updateData).Update()
	return err
}

// updateUserStatus 更新用户状态
func (s *lhbdService) updateUserStatus(userID int, status int, resMsg *strings.Builder) {
	updateData := g.Map{
		"id":     uint64(userID),
		"res":    resMsg.String(),
		"status": int8(status),
	}
	_, err := g.DB("mysql_zlyc").Model("zlyc_migrate_users_lhbd").
		Data(updateData).
		Where("id", userID).
		Update()
	if err != nil {
		return
	}
}

// migrationResult 迁移结果包装器
type migrationResult struct {
	Message  string
	PhoneArr []string
}

func (r *migrationResult) ToMap() interface{} {
	return g.Map{
		"msg":      r.Message,
		"phoneArr": r.PhoneArr,
	}
}
